package spring.cloud.tasks.api.controller;


import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import spring.cloud.tasks.api.domain.task.TaskConfiguration;
import spring.cloud.tasks.api.service.TaskService;
import spring.cloud.tasks.api.service.impl.TaskConfigurationAndZooKeeperUtil;
import spring.cloud.tasks.api.utils.Response;
import spring.cloud.tasks.api.vo.UpdateJobConfigVo;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RequestMapping("/nameSpaces/tasks")
public class TaskController {


    @Resource
    private TaskService taskService;


    /**
     * 获取域下所有任务的名字
     *
     * @param nameSpace 域名
     * @return 全域任务名字
     */
    @RequestMapping(value = "/getTaskIdList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response getTaskIdList(@PathVariable String nameSpace) throws RuntimeException {
        return Response.success(taskService.getTaskIdList(nameSpace));
    }

    @RequestMapping(value = "/getTaskAllocatedStatus", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response getTaskAllocatedStatus(@PathVariable String nameSpace,
                                           @RequestParam(required = false) List<String> taskIds) throws RuntimeException {
        Map<String, String> jobShardingMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(taskIds)) {
            for (String taskId : taskIds) {

            }
        }
        return Response.success(jobShardingMap);
    }


    @RequestMapping(value = "/task/enableTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response enableTask(final HttpServletRequest request,
                               @PathVariable String nameSpace,
                               @PathVariable String taskId) throws RuntimeException {
        //assertIsPermitted(PermissionKeys.jobEnable, nameSpace);
        taskService.enableTask(nameSpace, taskId, "");
        return new Response();
    }

    @RequestMapping(value = "/task/batchEnableTaskList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response batchEnableTaskList(final HttpServletRequest request,
                                        @PathVariable String nameSpace,
                                        @RequestParam List<String> taskIds) throws RuntimeException {


        for (String taskId : taskIds) {
            taskService.enableTask(nameSpace, taskId, "");
        }
        return new Response();
    }

    @RequestMapping(value = "/task/disableTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response disableTask(final HttpServletRequest request,
                                @PathVariable String nameSpace,
                                @PathVariable String taskId) throws RuntimeException {

        taskService.disableTask(nameSpace, taskId, "");
        return new Response();
    }


    @RequestMapping(value = "/task/disableTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response disableTask(final HttpServletRequest request,
                                @PathVariable String nameSpace,
                                @RequestParam List<String> taskIds) throws RuntimeException {

        for (String taskId : taskIds) {
            taskService.disableTask(nameSpace, taskId, "");
        }
        return new Response();
    }

    @RequestMapping(value = "/task/deleteTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response deleteTask(final HttpServletRequest request,
                               @PathVariable String nameSpace,
                               @PathVariable String taskId) throws RuntimeException {
        //assertIsPermitted(PermissionKeys.jobRemove, nameSpace);
        taskService.deleteTask(nameSpace, taskId, "");
        return new Response();
    }

    @RequestMapping(value = "/task/batchDeleteTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response batchDeleteTask(final HttpServletRequest request,
                                    @PathVariable String nameSpace,
                                    @RequestParam List<String> taskIds) throws RuntimeException {

        List<String> successtaskIds = new ArrayList<>();
        List<String> failtaskIds = new ArrayList<>();
        for (String taskId : taskIds) {
            try {
                taskService.deleteTask(nameSpace, taskId, "");
                successtaskIds.add(taskId);
            } catch (Exception e) {
                failtaskIds.add(taskId);
                log.info("remove job failed", e);
            }
        }
        if (!failtaskIds.isEmpty()) {
            StringBuilder message = new StringBuilder();
            message.append("删除成功的任务:").append(successtaskIds).append("，").append("删除失败的任务:").append(failtaskIds);
            throw new RuntimeException(message.toString());
        }
        return new Response();
    }

    /**
     * 批量设置任务的优先Executor
     */
    @RequestMapping(value = "/task/batchSetPreferExecutorIdList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response batchSetPreferExecutorIdList(final HttpServletRequest request,
                                                 @PathVariable String nameSpace,
                                                 @RequestParam List<String> taskIds,
                                                 @RequestParam String preferList) throws RuntimeException {
        for (String taskId : taskIds) {
            taskService.setPreferExecutorIdList(nameSpace, taskId, preferList);
        }
        return new Response();
    }


    @RequestMapping(value = "/task/addTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response addTask(final HttpServletRequest request,
                            @PathVariable String nameSpace, TaskConfiguration taskConfiguration)
            throws RuntimeException {
        //assertIsPermitted(PermissionKeys.jobAdd, nameSpace);
        Map<String, Object> reqParams = new HashMap<>();
        TaskConfigurationAndZooKeeperUtil.constructJobConfigOfCreate(nameSpace, taskConfiguration, reqParams);
        taskService.addTask(nameSpace, taskConfiguration, "");
        return new Response();
    }


    /**
     * 获取该任务可选择的优先Executor
     */
    @RequestMapping(value = "/task/getExecutorList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response getExecutors(final HttpServletRequest request, @PathVariable String nameSpace,
                                 @PathVariable String taskId) throws RuntimeException {
        return Response.success(taskService.getExecutorList(nameSpace, taskId));
    }


    @RequestMapping(value = "/task/runAtOnce", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response runAtOnce(@PathVariable String nameSpace,
                              @PathVariable String taskId) throws RuntimeException {
        final Map<String, Object> triggeredData = new HashMap<>();
        taskService.runAtOnce(nameSpace, taskId, triggeredData);
        return new Response();
    }


    @RequestMapping(value = "/task/stopAtOnce", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response stopAtOnce(@PathVariable String nameSpace,
                               @PathVariable String taskId) throws RuntimeException {
        final Map<String, Object> triggeredData = new HashMap<>();
        taskService.stopAtOnce(nameSpace, taskId, triggeredData);
        return new Response();
    }

    @RequestMapping(value = "/task/getTaskConfigurationVo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @GetMapping
    public Response getTaskConfigurationVo(final HttpServletRequest request,
                                           @PathVariable String nameSpace,
                                           @PathVariable String taskId) throws RuntimeException {
        return Response.success(taskService.getTaskConfigurationVo(nameSpace, taskId));
    }


    @RequestMapping(value = "/task/updateTaskConfiguration", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response updateTaskConfiguration(final HttpServletRequest request,
                                            @PathVariable String nameSpace,
                                            @PathVariable String taskId, UpdateJobConfigVo updateJobConfigVo)
            throws RuntimeException {
        //assertIsPermitted(PermissionKeys.jobUpdate, nameSpace);
        taskService.updateTaskConfiguration(nameSpace, updateJobConfigVo.toTaskConfiguration());
        return new Response();
    }

    @RequestMapping(value = "/task/updateJobCron", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Object> updateJobCron(@PathVariable("nameSpace") String nameSpace,
                                                @PathVariable("taskId") String taskId,
                                                @RequestBody Map<String, String> params,
                                                HttpServletRequest request) throws RuntimeException {
        HttpHeaders httpHeaders = new HttpHeaders();
        try {
            String cronExpression = params.remove("cronExpression");
            String pausePeriodDate = params.remove("pausePeriodDate");
            String pausePeriodTime = params.remove("pausePeriodTime");
            taskService.updateTaskCronExpression(nameSpace, taskId, cronExpression, pausePeriodDate, pausePeriodTime);
            return new ResponseEntity<>(httpHeaders, HttpStatus.OK);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @RequestMapping(value = "/task/getTaskConfigurationList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Object> getTaskConfigurationList(@PathVariable("nameSpace") String nameSpace)
            throws RuntimeException {
        HttpHeaders httpHeaders = new HttpHeaders();
        try {
            List<TaskConfiguration> taskConfigurationList = taskService.getTaskConfigurationList(nameSpace);
            return new ResponseEntity<Object>(taskConfigurationList, httpHeaders, HttpStatus.OK);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }


    @RequestMapping(value = "/getRestAPIJobInfo", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Object> query(@PathVariable("nameSpace") String nameSpace,
                                        @PathVariable("taskId") String taskId) throws RuntimeException {
        HttpHeaders httpHeaders = new HttpHeaders();
        try {
            TaskConfiguration taskInfo = taskService.getTaskInfo(nameSpace, taskId);
            return new ResponseEntity<Object>(taskInfo, httpHeaders, HttpStatus.OK);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }


    @RequestMapping(value = "/getRestApiJobInfos", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Object> queryAll(@PathVariable("nameSpace") String nameSpace)
            throws RuntimeException {
        HttpHeaders httpHeaders = new HttpHeaders();
        try {
            List<TaskConfiguration> apiJobInfos = taskService.getTaskInfoList(nameSpace);
            return new ResponseEntity<Object>(apiJobInfos, httpHeaders, HttpStatus.OK);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 获取任务执行状态
     */
    @RequestMapping(value = "/task/getTaskItemExecuteInfoList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response getExecutionStatus(final HttpServletRequest request, @PathVariable String nameSpace,
                                       @PathVariable String taskId) throws RuntimeException {
        return Response.success(taskService.getTaskItemExecuteInfoList(nameSpace, taskId));
    }

    /**
     * 获取任务执行状态
     */
    @RequestMapping(value = "/task/getTaskExecutorStatusInfoList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @GetMapping(value = "/getTaskExecutorStatusInfoList")
    public Response getTaskExecutorStatusList(final HttpServletRequest request, @PathVariable String nameSpace,
                                              @PathVariable String taskId) throws RuntimeException {
        return Response.success(taskService.getTaskExecutorStatusInfoList(nameSpace, taskId));
    }

    /**
     * 获取任务执行状态
     */
    @RequestMapping(value = "/task/getTaskExecutorList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Response getTaskExecutorList(final HttpServletRequest request, @PathVariable String nameSpace,
                                        @PathVariable String taskId) throws RuntimeException {
        return Response.success(taskService.getTaskExecutorList(nameSpace, taskId));
    }
}
